package com.sxhalo.fsms.socket;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;

import javax.websocket.*;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.springframework.stereotype.Component;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

@Component
@ServerEndpoint("/ws/{user}")
public class WebSocketServer {
	
	// 静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
	private static final AtomicInteger onlineCount = new AtomicInteger(0);
	// concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话，可以使用Map来存放，其中Key可以为用户标识
	private static CopyOnWriteArraySet<Session> sessionSet = new CopyOnWriteArraySet<Session>();
	// json
	private static ObjectMapper objectMapper = new ObjectMapper();
	/**
	 * 连接建立成功调用的方法
	 */
	@OnOpen
	public void onOpen(Session session, @PathParam("user") String user) {
		sessionSet.add(session); // 加入set中
		onlineCount.incrementAndGet(); // 在线数加1
	}

	/**
	 * 连接关闭调用的方法
	 */
	@OnClose
	public void onClose(Session session) {
		sessionSet.remove(session); // 从set中删除
		onlineCount.decrementAndGet(); // 在线数减1
	}

	/**
	 * 收到客户端消息后调用的方法
	 */
	@OnMessage
	public void onMessage(String message, Session session) {
		if ("heartbeat".equals(message)) {
			sendMessage(message, session);
		} else {
			if ("removeId".equals(message)) {
				session.getUserProperties().remove("deviceId");
			} else {
				session.getUserProperties().put("deviceId", message);
			}
		}
	}

	/**
	 * 发生错误时调用
	 */
	@OnError
	public void onError(Session session, Throwable error) {
		error.printStackTrace();
	}

	public static void sendMessage(String message) {
		for (Session session : sessionSet) {
			if (session.isOpen()) {
				sendMessage(message, session);
			}
		}
	}
	
	public static void sendMessage(Map<String, Object> msgData) {
		String json = null;
		try {
			json = objectMapper.writeValueAsString(msgData);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		if (json != null) {
			sendMessage(json);
		}
	}


	public static void sendMessage(String message, Session session) {
		try {
			session.getBasicRemote().sendText(message);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static CopyOnWriteArraySet<Session> getSessionSet() {
		return sessionSet;
	}

	public static AtomicInteger getOnlinecount() {
		return onlineCount;
	}
}
